/**
 * Created by spatra on 14-12-3.
 */

define(['angular', 'commonJS/module', 'angularMocks'], function(angular){

  describe('Unit: 通用模块 Services 测试', function(){

    //注入当前的ngModule
    beforeEach( module('TeamMindmap.common') );

    //对服务: ResourceService 进行测试
    describe('ResourceService', function(){
      var $httpBackend, ResourceService, testAccessor;
      var testBaseUrl = 'api_prefix/testResource';

      var mockData = {
        id: 123,
        name: 'mock',
        label: '测试'
      };

      //进行一些测试前的初始化工作
      beforeEach(inject(function(_$httpBackend_, _ResourceService_){
        $httpBackend = _$httpBackend_;
        ResourceService = _ResourceService_;
        testAccessor = ResourceService.getResourceAccessor({
          resourceName: 'testResource',
          apiPrefix: 'api_prefix'
        })
      }));

      afterEach(function(){
        $httpBackend.flush();
      });

      it('method: get', function(){
        var mockList = ['a', 'b', 'c'];
        $httpBackend.expectGET(testBaseUrl).respond(200, mockList);

        testAccessor.get()
          .success(function(data){
            expect(data).toEqual(mockList);
          });
      });

      it('method: store', function(){
        $httpBackend.expectPOST(testBaseUrl, mockData).respond(200, {id: mockData.id});

        testAccessor.store(mockData)
          .success(function(data){
            expect(data.id).toEqual(mockData.id);
          });
      });

      it('method: update', function(){
        $httpBackend.expectPUT(testBaseUrl + '/' + mockData.id, mockData).respond(200);

        testAccessor.update(mockData.id, mockData);
      });

      it('method: destroy', function(){
        $httpBackend.expectDELETE(testBaseUrl + '/' + mockData.id).respond(200);

        testAccessor.destroy(mockData.id);
      });

      it('method: show', function(){
        $httpBackend.expectGET(testBaseUrl + '/' + mockData.id).respond(200, mockData);

        testAccessor.show(mockData.id);

      });
    });// End of --> ResourceService

    //对服务: NestedResourceService 进行测试
    describe('NestedResourceService', function(){
      var $httpBackend, NestedResourceService, testAccessor;
      var testParentResourceName = 'testParent', testParentResourceId = 1 ,
        testNestResourceName = 'testNested', mockStateParams = {}, testApiPrefix = 'api_prefix';

      var testBaseUrl = [testApiPrefix, testParentResourceName,
        testParentResourceId, testNestResourceName]
        .join('/');

      var mockData = {
        id: 1,
        name: 'mock',
        label: '测试'
      };

      function initParentResource(){
        mockStateParams[ testParentResourceName + 'Id' ] = testParentResourceId;

        testAccessor['setParentResourceId'](mockStateParams);
      }

      beforeEach(inject(function(_$httpBackend_, _NestedResourceService_){
        $httpBackend = _$httpBackend_;
        NestedResourceService = _NestedResourceService_;
        testAccessor = NestedResourceService.getResourceAccessor({
          'parentResourceName': testParentResourceName,
          'nestedResourceName': testNestResourceName,
           apiPrefix: testApiPrefix
        });
      }));

      //注意, 在这里实现刷新
      afterEach(function(){
        $httpBackend.flush();
      });

      it('method: get', function(){
        initParentResource();
        var mockGetData = ['a', 'b', 'c'];
        $httpBackend.expectGET(testBaseUrl).respond(200, mockGetData);

        testAccessor.get()
          .success(function(data){
            expect(data).toEqual(mockGetData);
          });
      });

      it('method: show', function(){
        initParentResource();
        $httpBackend.expectGET(testBaseUrl + '/' + mockData.id).respond(200, mockData);

        testAccessor.show(mockData.id)
          .success(function(data){
            expect(data).toEqual(mockData);
          });
      });

      it('method: update', function(){
        initParentResource();
        $httpBackend.expectPUT(testBaseUrl + '/' + mockData.id).respond(200);

        testAccessor.update(mockData.id, mockData);
      });

      it('method: store', function(){
        initParentResource();
        $httpBackend.expectPOST(testBaseUrl, mockData).respond(200, {id: mockData.id});

        testAccessor.store(mockData)
          .success(function(data){
            expect(data.id).toEqual(mockData.id);
          });
      });

      it('method: destroy', function(){
        initParentResource();
        $httpBackend.expectDELETE(testBaseUrl + '/' + mockData.id).respond(200);

        testAccessor.destroy(mockData.id);
      });

    });//End of --> NestedResourceService

    describe('ClassHelperService', function(){
      var ClassHelperService;

      //测试使用的父类
      function Parent(){}
      Parent.prototype = {
        constructor: Parent,
        testMethod: function(){
          return 'Parent'
        }
      };

      //测试使用的派生类
      function Child(){}

      beforeEach(inject(function(_ClassHelperService_){
        ClassHelperService = _ClassHelperService_;
      }));

      it('method: extend', function(){
        ClassHelperService.extend(Child, Parent);

        var obj = new Child;

        expect( obj.testMethod()).toEqual('Parent');
        expect( obj instanceof Parent).toBe(true);
      });

      it('method: extendOrOverloadMethod', function(){
        ClassHelperService.extend(Child, Parent);
        ClassHelperService.extendOrOverloadMethod(Child, 'testMethod', function(){
          return 'Child'
        });

        var obj = new Child;

        expect( obj instanceof Parent).toBe(true);
        expect( obj.testMethod()).toEqual('Child');
      });

      it('method: objectEquals', function(){
        var aObj = {'name': 'value', 'changed': 'changed'};
        var bObj = {'name': 'value', 'changed': 'changed'};

        expect( ClassHelperService.objectEquals(aObj, bObj) ).toBe(true);

        bObj['changed'] = 'add';
        expect( ClassHelperService.objectEquals(aObj, bObj) ).toBe(false);

        expect( ClassHelperService.objectEquals('notObject', 'notObject') ).toBe(true);
        expect( ClassHelperService.objectEquals(123, 'notObject') ).toBe(false);
      });

      it('method: clone', function(){
        var oldObj = new Parent();
        oldObj['name'] = 'oldValue';

        var newObj = ClassHelperService.clone(oldObj);

        expect(newObj instanceof Parent).toBe(true);
        expect( ClassHelperService.objectEquals(newObj, oldObj) ).toBe(true);
        expect( newObj == oldObj ).toBe(false);

        expect( ClassHelperService.clone('notObject') ).toEqual('notObject');
      });

      it('method: update', function(){
        var fromObj = {name: 'from', add: 'add'};
        var toObj = {name: 'to'};

        ClassHelperService.update(fromObj, toObj);

        expect( ClassHelperService.objectEquals(fromObj, toObj) ).toBe(true);
      });

    });//End of --> ClassHelperService

    describe('LoginStatusService', function(){
      var LoginStatusService, $cookieStore;
      var mockData = {
        userInfo: {name: 'mock'},
        uri: {'logout': 'logout'}
      };
      var dataKey = 'loginData';

      beforeEach(inject(function(_LoginStatusService_, _$cookieStore_){
        LoginStatusService = _LoginStatusService_;
        $cookieStore = _$cookieStore_;

        $cookieStore.put(dataKey, mockData);
      }));

      it('method: init', function(){
        LoginStatusService.init(dataKey);

        expect(LoginStatusService.get('userInfo')).toBeDefined();
        expect( $cookieStore.get(dataKey) ).toBeUndefined();
      });

      it('method: get', function(){
        LoginStatusService.init(dataKey);

        expect(mockData['userInfo']['name']).toEqual( LoginStatusService.get('userInfo.name') );
      });
    });//End of --> LoginStatusService

    describe('DatetimeHelperService', function(){
      var DatetimeHelperService;
      var oneDaySeconds = 1000 * 60 * 60 *24;

      function getDateString(datetime){
        return datetime.getFullYear() + '-'
          + (datetime.getMonth() + 1) + '-'
          + datetime.getDate();
      }

      beforeEach(inject(function(_DatetimeHelperService_){
        DatetimeHelperService = _DatetimeHelperService_;
      }));

      it('method: setNow/getNow', function(){
        DatetimeHelperService.setNow('1993-03-09');

        expect(DatetimeHelperService.getNow()).toBeDefined();
        expect( DatetimeHelperService.getNow() instanceof Date );
      });

      it('method: checkRange', function(){
        DatetimeHelperService.setNow(); //重置

        var currentDatetime = new Date;

        //检查判断是否是当天
        expect( DatetimeHelperService.checkRange(currentDatetime, 'today')).toBeTruthy();
        expect( DatetimeHelperService.checkRange( getDateString(currentDatetime), 'today' ) ).toBeTruthy();
        expect( DatetimeHelperService.checkRange( '1993-03-09', 'today')).toBeFalsy();

        //添加是否从当前时间点计算，后两天之内
        expect(DatetimeHelperService.checkRange( currentDatetime.getTime() + oneDaySeconds, 'twodays') ).toBeTruthy();
        expect( DatetimeHelperService.checkRange( currentDatetime.getTime() + oneDaySeconds * 3, 'twodays')).toBeFalsy();

        //检查两个日期是否处于同一周
        DatetimeHelperService.setNow('2014-12-24');
        expect(DatetimeHelperService.checkRange('2014-12-25', 'week') ).toBeTruthy();
        expect(DatetimeHelperService.checkRange('2014-12-20', 'week')).toBeFalsy();

        //检查两个日期是否处于同一个年月
        DatetimeHelperService.setNow('1993-03-09');
        expect( DatetimeHelperService.checkRange('1993-03-10', 'month') ).toBeTruthy();
        expect( DatetimeHelperService.checkRange('1993-04-09', 'month') ).toBeFalsy();
        expect( DatetimeHelperService.checkRange('1992-03-09', 'month') ).toBeFalsy();
      });
    });//End of --> DatetimeHelperService

  });// End of --> Unit: 通用模块 Services 测试


});